package com.dferreira.axil.rest;

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;

import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.ValidationException;
import javax.validation.Validator;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.GenericEntity;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import com.dferreira.axil.data.RepositorioDeClientes;
import com.dferreira.axil.model.Cliente;
import com.dferreira.axil.service.CadastroDeCliente;

@Path("/clientes")
@RequestScoped
public class ClienteRESTService {

    @Inject
    private Logger log;

    @Inject
    private Validator validator;

    @Inject
    private RepositorioDeClientes repositorio;

    @Inject
    private CadastroDeCliente cadastro;

    @GET
    @Produces(MediaType.APPLICATION_XML)
    public Response listarTodos() {
    	GenericEntity<List<Cliente>> entity = new GenericEntity<List<Cliente>>(repositorio.findAllOrderedByName()){};
    	return Response.ok(entity).header("Content-Disposition", "attachment; filename=clientes.xml").build();
    }

    @GET
    @Path("/{id:[0-9][0-9]*}")
    public Response lookupMemberById(@PathParam("id") long id) {
        Cliente cliente = repositorio.findById(id);
        if (cliente == null)
            throw new WebApplicationException(Response.Status.NOT_FOUND);
        return Response.ok(cliente).header("Content-Disposition", "attachment; filename=" + id + "-" + cliente.getNome() + ".xml").build();
    }

    @POST
    @Consumes(MediaType.APPLICATION_XML)
    @Produces(MediaType.APPLICATION_XML)
    public Response salvarCliente(Cliente cliente) {

        Response.ResponseBuilder builder = null;

        try {
            validarCliente(cliente);

            cadastro.salvar(cliente);

            builder = Response.ok();
        } catch (ConstraintViolationException ce) {
            builder = createViolationResponse(ce.getConstraintViolations());
        } catch (Exception e) {
            Map<String, String> responseObj = new HashMap<String, String>();
            responseObj.put("error", e.getMessage());
            builder = Response.status(Response.Status.BAD_REQUEST).entity(responseObj);
        }

        return builder.build();
    }

    private void validarCliente(Cliente cliente) throws ConstraintViolationException, ValidationException {
        Set<ConstraintViolation<Cliente>> violations = validator.validate(cliente);

        if (!violations.isEmpty()) {
            throw new ConstraintViolationException(new HashSet<ConstraintViolation<?>>(violations));
        }
    }

    private Response.ResponseBuilder createViolationResponse(Set<ConstraintViolation<?>> violations) {
        log.fine("Validation completed. violations found: " + violations.size());

        Map<String, String> responseObj = new HashMap<String, String>();

        for (ConstraintViolation<?> violation : violations) {
            responseObj.put(violation.getPropertyPath().toString(), violation.getMessage());
        }

        return Response.status(Response.Status.BAD_REQUEST).entity(responseObj);
    }

}
